home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / games / nhak_src.zip / MAIL.C < prev    next >
C/C++ Source or Header  |  1993-03-16  |  9KB  |  401 lines

  1. /*    SCCS Id: @(#)mail.c    3.0    89/07/07
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /* block some unused #defines to avoid overloading some cpp's */
  6. #define MONATTK_H
  7. #include "hack.h"    /* mainly for index() which depends on BSD */
  8.  
  9. #ifdef MAIL
  10. static void FDECL(mdrush,(struct monst *,int,int));
  11. static void FDECL(mdappear,(struct monst *,BOOLEAN_P));
  12. static void NDECL(newmail);
  13.  
  14. # ifdef UNIX
  15. #  include <sys/stat.h>
  16. #  include <pwd.h>
  17. # endif
  18. # ifdef VMS
  19. #  include <descrip.h>
  20. #  include <ssdef.h>
  21. # endif
  22.  
  23. /*
  24.  * Notify user when new mail has arrived. [Idea from Merlyn Leroy, but
  25.  * I don't know the details of his implementation.]
  26.  * { Later note: he disliked my calling a general mailreader and felt that
  27.  *   hack should do the paging itself. But when I get mail, I want to put it
  28.  *   in some folder, reply, etc. - it would be unreasonable to put all these
  29.  *   functions in hack. }
  30.  *
  31.  * The mail daemon can move with less than usual restraint.  It can:
  32.  *    - move diagonally from a door
  33.  *    - use secret doors
  34.  *    - run thru a monster
  35.  *
  36.  * Its path should be longer when you are Telepat-hic and Blind.
  37.  *
  38.  * Possible extensions:
  39.  *    - Open the file MAIL and do fstat instead of stat for efficiency.
  40.  *      (But sh uses stat, so this cannot be too bad.)
  41.  *    - Examine the mail and produce a scroll of mail named "From somebody".
  42.  *    - Invoke MAILREADER in such a way that only this single letter is read.
  43.  *    - Do something to the text when the scroll is enchanted or cancelled.
  44.  */
  45.  
  46. /*
  47.  * { Note by Olaf Seibert: On the Amiga, we usually don't get mail.
  48.  *   So we go through most of the effects at 'random' moments. }
  49.  */
  50.  
  51. /*
  52.  * I found many bugs in this code, some dating back to Hack.
  53.  * Here are some minor problems i didn't fix:  -3.
  54.  *
  55.  *    - The code sometimes pops up the mail daemon next to you on
  56.  *      the corridor side of doorways when there are open spaces
  57.  *      within the room.
  58.  *    - It may also do this with adjoining castle rooms.
  59.  */
  60.  
  61. #ifdef OVL0
  62.  
  63. # if !defined(UNIX) && !defined(VMS)
  64. int mustgetmail = -1;
  65. # endif
  66.  
  67. #endif /* OVL0 */
  68. #ifdef OVLB
  69.  
  70. # ifdef UNIX
  71. extern struct passwd *getpwuid();
  72. static struct stat omstat,nmstat;
  73. static char *mailbox = NULL;
  74. static long laststattime;
  75.  
  76. # ifdef AMS                /* Just a placeholder for AMS */
  77. #   define MAILPATH "/dev/null"
  78. # else
  79. #  ifdef BSD
  80. #   define MAILPATH "/usr/spool/mail/"
  81. #  endif
  82. #  ifdef SYSV
  83. #   define MAILPATH "/usr/mail/"
  84. #  endif
  85. # endif /* AMS */
  86.  
  87. void
  88. getmailstatus() {
  89.     if(!mailbox && !(mailbox = getenv("MAIL"))) {
  90. #  ifdef MAILPATH
  91. #   ifdef AMS
  92.             struct passwd ppasswd;
  93.  
  94.         bcopy(getpwuid(getuid()), &ppasswd, sizeof(struct passwd));
  95.         if (ppasswd.pw_dir) {
  96.              mailbox = (char *) alloc((unsigned) strlen(ppasswd.pw_dir)+sizeof(AMS_MAILBOX));
  97.              Strcpy(mailbox, ppasswd.pw_dir);
  98.              Strcat(mailbox, AMS_MAILBOX);
  99.         } else
  100.           return;
  101. #   else
  102.         mailbox = (char *) alloc(sizeof(MAILPATH)+8);
  103.         Strcpy(mailbox, MAILPATH);
  104.         Strcat(mailbox, getpwuid(getuid())->pw_name);
  105. #  endif /* AMS */
  106. #  else
  107.         return;
  108. #  endif
  109.     }
  110.     if(stat(mailbox, &omstat)){
  111. #  ifdef PERMANENT_MAILBOX
  112.         pline("Cannot get status of MAIL=\"%s\".", mailbox);
  113.         mailbox = 0;
  114. #  else
  115.         omstat.st_mtime = 0;
  116. #  endif
  117.     }
  118. }
  119. # endif /* UNIX */
  120.  
  121. # ifdef VMS
  122. extern unsigned long pasteboard_id;
  123. volatile int broadcasts = 0;
  124. #  define getmailstatus()
  125. # endif /* VMS */
  126.  
  127.  
  128. /* make mail daemon run through the dungeon */
  129. static void
  130. mdrush(md,fx,fy)
  131. struct monst *md;
  132. register int fx, fy;    /* origin, where the '&' is displayed */
  133. {
  134.     register int tx = md->mx, ty = md->my;
  135.             /* real location, where the '&' is going */
  136.  
  137.     tmp_at(-1, md->data->mlet);    /* open call */
  138. #ifdef TEXTCOLOR
  139.     tmp_at(-3, (int)md->data->mcolor);
  140. #endif
  141.  
  142.     while(fx != tx || fy != ty) {
  143.         register int dx, dy,        /* direction counters */
  144.                  nfx = fx, nfy = fy,/* next location */ 
  145.                  d1, d2;        /* shortest dist, eval */
  146.  
  147.         /* display the '&' at (fx,fy) */
  148.         tmp_at(fx,fy);
  149.  
  150.         /* find location next to (fx,fy) closest to (tx,ty) */
  151.         d1 = dist2(fx,fy,tx,ty);
  152.         for(dx = -1; dx <= 1; dx++) for(dy = -1; dy <= 1; dy++)
  153.             if((dx || dy) && isok(fx+dx,fy+dy) && 
  154.                !IS_STWALL(levl[fx+dx][fy+dy].typ)) {
  155.             d2 = dist2(fx+dx,fy+dy,tx,ty);
  156.             if(d2 < d1) {
  157.                 d1 = d2;
  158.                 nfx = fx+dx;
  159.                 nfy = fy+dy;
  160.             }
  161.             }
  162.  
  163.         /* set (fx,fy) to next location, unless it stopped */
  164.         if(nfx != fx || nfy != fy) {
  165.             fx = nfx;
  166.             fy = nfy;
  167.         } else break;
  168.     }
  169.  
  170.     tmp_at(-1,-1);            /* close call */
  171. }
  172.  
  173. static void
  174. mdappear(md,away)
  175. struct monst *md;
  176. boolean away;
  177. {
  178.     static int fx, fy;            /* origin */
  179.     int tx = md->mx, ty = md->my;        /* destination */
  180.     register int uroom = inroom(u.ux, u.uy);/* room you're in */
  181.  
  182.     /* if mail daemon is in same room as you */
  183.     if(uroom >= 0 && inroom(md->mx,md->my) == uroom && (!Blind || Telepat))
  184.         if(away) {
  185.             unpmon(md);
  186.             remove_monster(tx, ty);
  187.  
  188.             /* fake "real" location to origin */
  189.             md->mx = fx; md->my = fy;
  190.  
  191.             /* rush from destination */
  192.             mdrush(md,tx,ty);
  193.             return;
  194.         } else {
  195.             /* choose origin */
  196.             register int cnt = rooms[uroom].doorct;
  197.             register int tmp = rooms[uroom].fdoor;
  198.             register int dd = 0;
  199.  
  200.             /* which door (or staircase) is farthest? */
  201.             while (cnt--) {
  202.                 if(dd < dist(doors[tmp].x, doors[tmp].y)) {
  203.                     fx = doors[tmp].x;
  204.                     fy = doors[tmp].y;
  205.                     dd = dist(tx,ty);
  206.                 }
  207.                 tmp++;
  208.             }
  209.             if (has_dnstairs(&rooms[uroom]))
  210.                 if(dd < dist(xdnstair, ydnstair)) {
  211.                     fx = xdnstair;
  212.                     fy = ydnstair;
  213.                     dd = dist(xdnstair, ydnstair);
  214.                 }
  215.             if (has_upstairs(&rooms[uroom]))
  216.                 if(dd < dist(xupstair, yupstair)) {
  217.                     fx = xupstair;
  218.                     fy = yupstair;
  219.                 }
  220.  
  221.             /* rush from origin */
  222.             mdrush(md,fx,fy);
  223.         }
  224.  
  225.     pmon(md);
  226. }
  227.  
  228. static void
  229. newmail() {
  230.     struct obj *obj;
  231.     /* deliver a scroll of mail */
  232.     register boolean invload =
  233.         ((inv_weight() + (int)objects[SCR_MAIL].oc_weight) > 0 ||
  234.              Fumbling);
  235.     register struct monst *md = makemon(&mons[PM_MAIL_DAEMON], u.ux, u.uy);
  236.  
  237.     if(!md)    return;
  238.  
  239.     mdappear(md,FALSE);
  240.  
  241. # ifdef VMS
  242.     pline("\"Hello, %s!  I have a message for you.\"", plname);
  243. # else
  244. #  ifdef NO_MAILREADER
  245.     pline("\"Hello, %s!  You have some mail in the outside world.\"", plname);
  246. #  else
  247.     pline("\"Hello, %s!  I have some mail for you.\"", plname);
  248. # endif
  249. # endif
  250.  
  251. # ifndef NO_MAILREADER
  252.     if(dist(md->mx,md->my) > 2)
  253.         verbalize("Catch!");
  254.     more();
  255.     obj = mksobj(SCR_MAIL, FALSE);
  256.     obj->known = obj->dknown = TRUE;
  257.     makeknown(SCR_MAIL);
  258.     if (!invload) obj = addinv(obj);
  259.     if(invload || inv_cnt() > 52) {
  260.         if (invload) dropy(obj);
  261.         else dropx(obj);
  262.         stackobj(fobj);        
  263.         verbalize("Oops!");
  264.     } else {
  265.         int savequan = obj->quan;
  266.         obj->quan = 1;
  267.         prinv(obj);
  268.         obj->quan = savequan;
  269.     }
  270. # endif /* NO_MAILREADER */
  271.  
  272.     /* disappear again */
  273.     mdappear(md,TRUE);
  274.     mongone(md);
  275.  
  276.     /* force the graphics character set off */
  277.     nscr();
  278. # ifdef VMS
  279.     broadcasts--;
  280. # endif
  281. }
  282.  
  283. #endif /* OVLB */
  284.  
  285. # if !defined(UNIX) && !defined(VMS)
  286.  
  287. #ifdef OVL0
  288.  
  289. void
  290. ckmailstatus() {
  291.     if (mustgetmail < 0)
  292.         return;
  293.     if (--mustgetmail <= 0) {
  294.         newmail();
  295.         mustgetmail = -1;
  296.     }
  297. }
  298.  
  299. #endif /* OVL0 */
  300. #ifdef OVLB
  301.  
  302. void
  303. readmail()
  304. {
  305.     pline("It says:  \"Please disregard previous letter.\"");
  306. }
  307.  
  308. #endif /* OVLB */
  309.  
  310. # endif /* !UNIX && !VMS */
  311.  
  312. # ifdef UNIX
  313.  
  314. #ifdef OVL0
  315.  
  316. void
  317. ckmailstatus() {
  318.     if(!mailbox
  319. #  ifdef MAILCKFREQ
  320.             || moves < laststattime + MAILCKFREQ
  321. #  endif
  322.                             )
  323.         return;
  324.  
  325.     laststattime = moves;
  326.     if(stat(mailbox, &nmstat)){
  327. #  ifdef PERMANENT_MAILBOX
  328.         pline("Cannot get status of MAIL=\"%s\" anymore.", mailbox);
  329.         mailbox = 0;
  330. #  else
  331.         nmstat.st_mtime = 0;
  332. #  endif
  333.     } else if(nmstat.st_mtime > omstat.st_mtime) {
  334.         if(nmstat.st_size)
  335.             newmail();
  336.         getmailstatus();    /* might be too late ... */
  337.     }
  338. }
  339.  
  340. #endif /* OVL0 */
  341. #ifdef OVLB
  342.  
  343. void
  344. readmail() {
  345. #  ifdef DEF_MAILREADER            /* This implies that UNIX is defined */
  346.     register char *mr = 0;
  347.     more();
  348.     if(!(mr = getenv("MAILREADER")))
  349.         mr = DEF_MAILREADER;
  350.     if(child(1)){
  351.         (void) execl(mr, mr, NULL);
  352.         exit(1);
  353.     }
  354. #  else
  355. #   ifndef AMS              /* AMS mailboxes are directories */
  356.     (void) page_file(mailbox, FALSE);
  357. #   endif /* AMS */
  358. #  endif /* DEF_MAILREADER */
  359.  
  360.     /* get new stat; not entirely correct: there is a small time
  361.        window where we do not see new mail */
  362.     getmailstatus();
  363. }
  364.  
  365. #endif /* OVLB */
  366.  
  367. # endif /* UNIX */
  368.  
  369. # ifdef VMS
  370.  
  371. #ifdef OVL0
  372.  
  373. void
  374. ckmailstatus()
  375. {
  376.     if (broadcasts)
  377.         newmail();
  378. }
  379.  
  380. #endif /* OVL0 */
  381. #ifdef OVLB
  382.  
  383. void
  384. readmail()
  385. {
  386.     char buf[16384];    /* $BRKTHRU limits messages to 16350 bytes */
  387.     $DESCRIPTOR(message, buf);
  388.     short length;
  389.  
  390.     if (SMG$GET_BROADCAST_MESSAGE(&pasteboard_id, &message, &length)
  391.         == SS$_NORMAL && length != 0) {
  392.         buf[length] = '\0';
  393.         pline("%s", buf);
  394.     }
  395. }
  396. # endif /* VMS */
  397.  
  398. #endif /* OVLB */
  399.  
  400. #endif /* MAIL */
  401.